package com.freight.tws.third;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.ocr_api20210707.Client;
import com.aliyun.ocr_api20210707.models.*;
import com.aliyun.tea.*;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.Common;
import com.aliyun.teautil.models.RuntimeOptions;
import com.freight.common.core.exception.ServiceException;
import com.freight.common.core.utils.StringUtils;
import com.freight.message.api.RemoteMessageClient;
import com.freight.tws.api.RemoteConfigClient;
import com.freight.tws.api.domain.Driver;
import com.freight.tws.api.domain.Vehicle;
import com.freight.tws.domain.DriverBank;
import com.freight.tws.domain.TwsCompany;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 阿里云证件识别
 */
@Component
public class AliOcrService {

    @Autowired
    private RemoteConfigClient remoteConfigClient;

    @Autowired
    private RemoteMessageClient remoteMessageClient;

    /**
     * 身份证识别
     * @param imgUrl
     */
    public Driver ocrIdcard(String imgUrl) {
        try {
            Client client = createClient();
            RecognizeIdcardRequest recognizeIdcardRequest = new RecognizeIdcardRequest().setUrl(imgUrl);
            RuntimeOptions runtime = new RuntimeOptions();
            // 复制代码运行请自行打印 API 的返回值
            RecognizeIdcardResponse recognizeIdcardResponse = client.recognizeIdcardWithOptions(recognizeIdcardRequest, runtime);
            String driverMsg = JSON.toJSONString(recognizeIdcardResponse);
            if (StringUtils.isNotBlank(driverMsg)){
                JSONObject driver1 = JSON.parseObject(driverMsg);
                JSONObject driver2 = JSON.parseObject(driver1.getJSONObject("body").getString("data"));
                JSONObject cardType = driver2.getJSONObject("data").getJSONObject("face");
                int type = 1;
                if (cardType == null){
                    type = 2;
                    cardType = driver2.getJSONObject("data").getJSONObject("back");
                }
                JSONObject driver3 =cardType.getJSONObject("data");
                Driver driver = new Driver();
                if (type == 1){
                    driver.setDriverName(driver3.getString("name"));
                    driver.setSex(driver3.getString("sex"));
                    driver.setDrivingLicense(driver3.getString("idNumber"));
                }else {
                    //国徽面
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd");
                    String[] date = driver3.getString("validPeriod").split("-");
                    if (!"长期".equals(date[1]) && sdf.parse(sdf.format(new Date())).after(sdf.parse(date[1]))){
                        return null;
                    }
                }
                return driver;
            }
        } catch (TeaException error) {
            handleTeaException(error.code);
            Common.assertAsString(error.message);
        } catch (Exception _error) {
            TeaException error = new TeaException(_error.getMessage(), _error);
            Common.assertAsString(error.message);
        }

        return null;
    }

    /**
     * 驾驶证识别
     * @param imgUrl
     * @return
     */
    public Driver ocrCarIdcard(String imgUrl) {
        try {
            Client client = createClient();
            RecognizeDrivingLicenseRequest recognizeDrivingLicenseRequest = new RecognizeDrivingLicenseRequest().setUrl(imgUrl);
            RuntimeOptions runtime = new RuntimeOptions();
            // 复制代码运行请自行打印 API 的返回值
            RecognizeDrivingLicenseResponse recognizeDrivingLicenseResponse = client.recognizeDrivingLicenseWithOptions(recognizeDrivingLicenseRequest, runtime);
            String driverMsg = JSON.toJSONString(recognizeDrivingLicenseResponse);
            if (StringUtils.isNotBlank(driverMsg)) {
                JSONObject driver1 = JSON.parseObject(driverMsg);
                JSONObject driver2 = JSON.parseObject(driver1.getJSONObject("body").getString("data"));
                JSONObject driver3 = driver2.getJSONObject("data").getJSONObject("face").getJSONObject("data");
                driver3.getString("validPeriod");
                Driver driver = new Driver();
                driver.setVehicleClass(driver3.getString("approvedType"));
                driver.setIssuingOrganizations(driver3.getString("issueAuthority"));
                driver.setDrivingLicense(driver3.getString("licenseNumber"));
                String[] validDate = driver3.getString("validPeriod").split("至");
                driver.setValidPeriodFrom(DateUtil.parse(validDate[0],"yyyy-MM-dd"));
                driver.setValidPeriodTo(DateUtil.parse(validDate[1],"yyyy-MM-dd"));
                return driver;
            }
        } catch (TeaException error) {
            handleTeaException(error.code);
            Common.assertAsString(error.message);
        } catch (Exception _error) {
            TeaException error = new TeaException(_error.getMessage(), _error);
            Common.assertAsString(error.message);
        }
        return null;
    }

    /**
     * 行驶证识别
     * @param url
     * @return
     */
    public Vehicle ocrVehicleFace(String url) {
        try {
            Client client = createClient();
            RecognizeVehicleLicenseRequest recognizeVehicleLicenseRequest = new RecognizeVehicleLicenseRequest().setUrl(url);
            RuntimeOptions runtime = new RuntimeOptions();
            RecognizeVehicleLicenseResponse recognizeVehicleLicenseResponse = client.recognizeVehicleLicenseWithOptions(recognizeVehicleLicenseRequest,runtime);
            String vehicleMsg = JSON.toJSONString(recognizeVehicleLicenseResponse);
            if (StringUtils.isNotBlank(vehicleMsg)){
                JSONObject vehicle1 = JSON.parseObject(vehicleMsg);
                JSONObject vehicle2 = JSON.parseObject(vehicle1.getJSONObject("body").getString("data"));
                JSONObject cardType = vehicle2.getJSONObject("data").getJSONObject("face");
                int type = 1;
                if (cardType == null) {
                    type = 2;
                    cardType = vehicle2.getJSONObject("data").getJSONObject("back");
                }
                JSONObject vehicle3 = cardType.getJSONObject("data");
                Vehicle vehicle = new Vehicle();
                if (type == 1) {
                    // 正面
                    vehicle.setVehicleNumber(vehicle3.getString("licensePlateNumber"));
                    vehicle.setVehicleType(vehicle3.getString("vehicleType"));
                    vehicle.setOwner(vehicle3.getString("owner"));
                    vehicle.setUseCharacter(vehicle3.getString("useNature"));
                    vehicle.setVin(vehicle3.getString("vinCode"));
                    vehicle.setRegisterDate(DateUtil.parse(vehicle3.getString("registrationDate"),"yyyy-MM-dd"));
                    vehicle.setIssueDate(DateUtil.parse(vehicle3.getString("issueDate"),"yyyy-MM-dd"));
                    vehicle.setIssuingOrganizations(vehicle3.getString("issueAuthority"));
                } else {
                    // 背面
                    vehicle.setVehicleEnergyType(vehicle3.getString("energySign"));
                    vehicle.setVehicleNumber(vehicle3.getString("licensePlateNumber"));
                    String val0 = vehicle3.getString("totalWeight"); // 总质量
                    String val1 = vehicle3.getString("permittedWeight"); // 核定载质量
                    String val2 = vehicle3.getString("curbWeight"); // 整备质量
                    String val3 = vehicle3.getString("tractionWeight"); // 准牵引总质量
                    // 核定载质量：取 准牵引总质量 或 核定载质量
                    if (StringUtils.isNotBlank(val3)) {
                        String kg = val3.substring(0,val3.length() - 2);
                        vehicle.setVehicleTonnage(new BigDecimal(Double.parseDouble(kg)));
                    }
                    if (StringUtils.isNotBlank(val1)) {
                        String kg = val1.substring(0, val1.length() - 2);
                        vehicle.setVehicleTonnage(new BigDecimal(Double.parseDouble(kg)));
                    }
                    // 吨位，总质量：取 (整备质量 + 准牵引总质量) 或 总质量
                    if (StringUtils.isNotBlank(val2)) {
                        String kg = val2.substring(0, val2.length() - 2);
                        BigDecimal b1 = new BigDecimal(Double.parseDouble(kg));
                        if(StringUtils.isNotBlank(val3)) {
                            String kgg = val3.substring(0,val3.length() - 2);
                            BigDecimal b2 = new BigDecimal(Double.parseDouble(kgg));
                            vehicle.setGrossMass(b1.add(b2));
                        } else {
                            vehicle.setGrossMass(vehicle.getVehicleTonnage());
                        }
                    }
                    if (StringUtils.isNotBlank(val0)) {
                        String kg = val0.substring(0, val0.length() - 2);
                        vehicle.setGrossMass(new BigDecimal(Double.parseDouble(kg)));
                    }
                }
                return vehicle;
            }
            return null;
        }catch (TeaException error) {
            handleTeaException(error.code);
            Common.assertAsString(error.message);
        } catch (Exception _error) {
            TeaException error = new TeaException(_error.getMessage(), _error);
            Common.assertAsString(error.message);
        }
        return null;
    }

    /**
     * 营业执照识别
     * @param url
     * @return
     */
    public TwsCompany ocrBusinessLicense(String url) {
        try {
            Client client = createClient();
            RecognizeBusinessLicenseRequest recognizeBusinessLicenseRequest = new RecognizeBusinessLicenseRequest().setUrl(url);
            RuntimeOptions runtime = new RuntimeOptions();
            RecognizeBusinessLicenseResponse recognizeBusinessLicenseResponse = client.recognizeBusinessLicenseWithOptions(recognizeBusinessLicenseRequest, runtime);
            String licenseMsg = JSON.toJSONString(recognizeBusinessLicenseResponse);
            if (StringUtils.isNotBlank(licenseMsg)) {
                JSONObject license1 = JSON.parseObject(licenseMsg);
                JSONObject license2 = JSON.parseObject(license1.getJSONObject("body").getString("data"));
                JSONObject info = license2.getJSONObject("data");
                TwsCompany twsCompany = new TwsCompany();
                twsCompany.setCompanyName(info.getString("companyName"));
                twsCompany.setTaxNo(info.getString("creditCode"));
                twsCompany.setAddress(info.getString("businessAddress"));
                twsCompany.setLegal(info.getString("legalPerson"));
                return twsCompany;
            }
            return null;
        } catch (TeaException error) {
            handleTeaException(error.code);
            Common.assertAsString(error.message);
        } catch (Exception _error) {
            TeaException error = new TeaException(_error.getMessage(), _error);
            Common.assertAsString(error.message);
        }
        return null;
    }

    /**
     * 银行卡识别
     * @param url
     * @return
     */
    public DriverBank ocrBank(String url) {
        try {
            Client client = createClient();
            RecognizeBankCardRequest recognizeBankCardRequest = new RecognizeBankCardRequest().setUrl(url);
            RuntimeOptions runtime = new RuntimeOptions();
            RecognizeBankCardResponse recognizeBankCardResponse = client.recognizeBankCardWithOptions(recognizeBankCardRequest, runtime);
            String licenseMsg = JSON.toJSONString(recognizeBankCardResponse);
            if (StringUtils.isNotBlank(licenseMsg)) {
                JSONObject license1 = JSON.parseObject(licenseMsg);
                JSONObject license2 = JSON.parseObject(license1.getJSONObject("body").getString("data"));
                JSONObject info = license2.getJSONObject("data");
                DriverBank driverBank = new DriverBank();
                driverBank.setCardType(info.getString("cardType"));
                driverBank.setBankName(info.getString("bankName"));
                driverBank.setCardNumber(info.getString("cardNumber"));
                driverBank.setValidToDate(info.getString("validToDate"));
                return driverBank;
            }
            return null;
        } catch (TeaException error) {
            handleTeaException(error.code);
            Common.assertAsString(error.message);
        } catch (Exception _error) {
            TeaException error = new TeaException(_error.getMessage(), _error);
            Common.assertAsString(error.message);
        }
        return null;
    }

    /**
     * 使用RAM访问控制账号初始化Client（需要账号有管理印刷文字识别(OCR)的权限）
     * @return Client
     * @throws Exception
     */
    private Client createClient() throws Exception {
        String accessKeyId = remoteConfigClient.selectConfigByKey("ali.accessKeyId");
        String accessKeySecret = remoteConfigClient.selectConfigByKey("ali.accessKeySecret");
        if(StringUtils.isEmpty(accessKeyId) || StringUtils.isEmpty(accessKeySecret)) {
            throw new ServiceException("RAM访问控制账号未配置");
        }
        Config config = new Config()
                // 必填，您的 AccessKey ID
                .setAccessKeyId(accessKeyId)
                // 必填，您的 AccessKey Secret
                .setAccessKeySecret(accessKeySecret);
        // 访问的域名
        config.endpoint = "ocr-api.cn-hangzhou.aliyuncs.com";
        return new Client(config);
    }

    /**
     * 处理错误
     * @param errCode 错误码
     */
    private void handleTeaException(String errCode) {
        String msg = "";
        switch (errCode) {
            case "OcrServiceExpired":
                msg = "阿里云OCR服务已经欠费过期";
                break;
            default:
                msg = "阿里云OCR服务异常: " + errCode;
                break;
        }
        // 发送企业微信通知
        remoteMessageClient.sendWeChatMessage(msg);
    }

}
